package com.aizuda.boot.modules.business.job;

import com.aizuda.boot.modules.business.contractNumber.domain.entity.ContractNumberRuleEntity;
import com.aizuda.boot.modules.business.contractNumber.domain.entity.ContractNumberSequenceEntity;
import com.aizuda.boot.modules.common.constant.enums.SequenceResetEnums;
import com.aizuda.boot.modules.business.contractNumber.service.ContractNumberRuleService;
import com.aizuda.boot.modules.business.contractNumber.service.ContractNumberSequenceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * @Author sangyirong
 * @ClassName NumberJob
 * @Version 1.0
 * @Date 2025/7/9 19:20
 */
@Slf4j
@Component
public class NumberJob {

    @Resource
    private ContractNumberRuleService contractNumberRuleService;

    @Resource
    private ContractNumberSequenceService contractNumberSequenceService;

    /**
     * 定时重置编号序号任务
     * XXL-JOB handler 方法
     */
    @XxlJob("restNumberHandler")
    public void resetNumberSequenceHandler() {
        log.info("开始执行编号序号重置定时任务");
        
        try {
            // 获取所有启用的编号规则
            List<ContractNumberRuleEntity> enabledRules = contractNumberRuleService.list(
                    new LambdaQueryWrapper<ContractNumberRuleEntity>()
                            .eq(ContractNumberRuleEntity::getIsEnabled, true)
                            .ne(ContractNumberRuleEntity::getSequenceReset, SequenceResetEnums.NO_RESET)
            );

            if (enabledRules.isEmpty()) {
                log.info("没有需要重置的编号规则");
                return;
            }

            int resetCount = 0;
            LocalDateTime now = LocalDateTime.now();

            for (ContractNumberRuleEntity rule : enabledRules) {
                if (shouldResetSequence(rule, now)) {
                    resetSequenceForRule(rule);
                    updateRuleResetTime(rule, now);
                    resetCount++;
                    log.info("重置编号规则[{}]的序号，规则ID: {}", rule.getRuleName(), rule.getId());
                }
            }

            log.info("编号序号重置定时任务执行完成，共重置 {} 个规则", resetCount);
            
        } catch (Exception e) {
            log.error("编号序号重置定时任务执行异常", e);
            throw e;
        }
    }

    /**
     * 判断是否需要重置序号
     * @param rule 编号规则
     * @param now 当前时间
     * @return 是否需要重置
     */
    private boolean shouldResetSequence(ContractNumberRuleEntity rule, LocalDateTime now) {
        Date resetTime = rule.getResetTime();
        if (resetTime == null) {
            // 如果没有重置时间记录，说明是第一次，需要重置
            return true;
        }

        LocalDateTime lastResetTime = resetTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        SequenceResetEnums resetStrategy = rule.getSequenceReset();

        switch (resetStrategy) {
            case DAILY:
                // 每天重置：检查是否跨天
                return !now.toLocalDate().equals(lastResetTime.toLocalDate());
                
            case MONTHLY:
                // 每月重置：检查是否跨月
                return now.getYear() != lastResetTime.getYear() || 
                       now.getMonthValue() != lastResetTime.getMonthValue();
                       
            case YEARLY:
                // 每年重置：检查是否跨年
                return now.getYear() != lastResetTime.getYear();
                
            case NO_RESET:
            default:
                return false;
        }
    }

    /**
     * 重置指定规则的序号
     * @param rule 编号规则
     */
    private void resetSequenceForRule(ContractNumberRuleEntity rule) {
        try {
            // 重置所有相关的序号记录为 1（从1开始计数）
            LambdaUpdateWrapper<ContractNumberSequenceEntity> updateWrapper = 
                    new LambdaUpdateWrapper<ContractNumberSequenceEntity>()
                            .eq(ContractNumberSequenceEntity::getRuleId, rule.getId())
                            .set(ContractNumberSequenceEntity::getCurrentNumber, 0) // 设置为0，下次生成时会+1变成1
                            .set(ContractNumberSequenceEntity::getGeneratedDate, new Date());

            boolean updateResult = contractNumberSequenceService.update(updateWrapper);
            
            if (updateResult) {
                log.debug("成功重置规则[{}]的所有序号记录", rule.getRuleName());
            } else {
                log.warn("重置规则[{}]的序号记录时无数据更新", rule.getRuleName());
            }
            
        } catch (Exception e) {
            log.error("重置规则[{}]序号时发生异常", rule.getRuleName(), e);
            throw e;
        }
    }

    /**
     * 更新规则的重置时间
     * @param rule 编号规则
     * @param resetTime 重置时间
     */
    private void updateRuleResetTime(ContractNumberRuleEntity rule, LocalDateTime resetTime) {
        try {
            Date resetDate = Date.from(resetTime.atZone(ZoneId.systemDefault()).toInstant());
            
            LambdaUpdateWrapper<ContractNumberRuleEntity> updateWrapper = 
                    new LambdaUpdateWrapper<ContractNumberRuleEntity>()
                            .eq(ContractNumberRuleEntity::getId, rule.getId())
                            .set(ContractNumberRuleEntity::getResetTime, resetDate);

            boolean updateResult = contractNumberRuleService.update(updateWrapper);
            
            if (updateResult) {
                log.debug("成功更新规则[{}]的重置时间", rule.getRuleName());
            } else {
                log.warn("更新规则[{}]的重置时间失败", rule.getRuleName());
            }
            
        } catch (Exception e) {
            log.error("更新规则[{}]重置时间时发生异常", rule.getRuleName(), e);
            throw e;
        }
    }
}
